﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.UI;
using FlickrXplorer.Web.Models;
using FlickrXplorer.Web.ViewData;
using FlickrXplorer.Web.Utilities;
using FlickrXplorer.Web.ViewData;

namespace FlickrXplorer.Web.Controllers
{
    [HandleError]
    public class PhotoController : Controller
    {
        private readonly IPhotoModel model;
        private readonly ISecurityModel secModel;
        private const int PHOTO_LIST_PAGE_LEN = 12;

        public PhotoController()
        {
            model = new PhotoModel();
            secModel = new SecurityModel();
        }

        public PhotoController(IPhotoModel model, ISecurityModel securityModel)
        {
            this.model = model;
            this.secModel = securityModel;
        }

        private void FileError(Exception ex)
        {
            string returnUrl = Request.GetStoredUrl();

            if (!string.IsNullOrEmpty(returnUrl))
            {
                ViewData["Message"] = ex.Message + " <a href=\"" + returnUrl + "\">lets go back</a>";
            }
            else
            {
                ViewData["Message"] = ex.Message + " at " + ex.Source;
            }
        }

        // get interesting photos returns crap if not filtered, so going for new method.
        private string most_popular = System.Configuration.ConfigurationManager.AppSettings["popular_words"];

        [CompressResponse, MvcAction]
        public ActionResult Index(string category, int? page, string style)
        {
            if (string.IsNullOrEmpty(category))
            {
                string[] parts = most_popular.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                int pIndex = new Random().Next(0, parts.Length - 1);
                category = parts[pIndex];
                // take randmon one
            }

            PhotoData photoData = new PhotoData();
            
            int pageValue = page == null ? 0 : page.Value - 1;
           
            photoData.Photos = model.GetInterestingPhotos(category, pageValue, PHOTO_LIST_PAGE_LEN);

            BuildPager(photoData);
       
            return ViewPhoto(style, photoData);
        }

        [MvcAction]
        public ActionResult NsId (string nsId, int? page, string style)
        {
            ViewData["NsId"] = nsId;

            PhotoData photoData = new PhotoData();

            int pageValue = page == null ? 0 : page.Value - 1;

            People people = model.GetPeopleForNsId(nsId);
            // null check.

            photoData.People = people;
            ViewData["User"] = people.Username;
            photoData.Photos = model.GetPhotosForNsId(nsId, pageValue,
                                                           PHOTO_LIST_PAGE_LEN);

            BuildPager(photoData);
       
            return ViewPhoto(style, photoData);
        }

        private void GetPhotosForPeople(PhotoData photoData, People people, int pageValue)
        {
            if (people != null)
            {
                photoData.People = people;
                ViewData["User"] = people.Username;
                photoData.Photos = model.GetPhotosByUser(people.Username, string.Empty, pageValue,
                                                               PHOTO_LIST_PAGE_LEN);
            }
            BuildPager(photoData);
        }

        [MvcAction]
        public new ActionResult User(string u, string q, int? page, string style)
        {
            string user = HttpUtility.UrlDecode(u, Encoding.UTF8);
            int pageValue = page == null ? 0 : page.Value - 1;

            PhotoData photoData = new PhotoData();

            People people = model.GetPeople(user);
            GetPhotosForPeople(photoData, people, pageValue);
    
            return ViewPhoto(style, photoData);
        }

        public enum  SearchType
        {
            Text,
            Tag,
            User
        }
        public enum ViewStyle
        {
            Full, 
            Widget
        }
     
        [MvcAction]
        public ActionResult Search(string q, string type, int ? page, string style)
        {
            ViewData["Search"] = q;
            ViewData["Url"] = this.ControllerContext.HttpContext.Request.Url.AbsolutePath;

            PhotoData photoData = GetPhotoData(q, type, page);
            return ViewPhoto(style, photoData);
        }

        private ActionResult ViewPhoto(string style, object model)
        {
            ViewStyle viewStyle = ViewStyle.Full;

            if (!string.IsNullOrEmpty(style))
            {
                string lowerType = style.ToLower();
                style = lowerType.Substring(0, 1).ToUpper() + lowerType.Substring(1, lowerType.Length - 1);

                try
                {
                    viewStyle = (ViewStyle) Enum.Parse(typeof(ViewStyle), style);
                }
                catch
                {
                    // dont do anything for now.
                }
            }
            
            if (viewStyle == ViewStyle.Widget)
                return View("ImageListControl", model);

            return View(model);
        }

        private PhotoData GetPhotoData(string q, string type, int? page)
        {
            SearchType searchType = SearchType.Text;

            if (!string.IsNullOrEmpty(type))
            {
                string lowerType = type.ToLower();
                type = lowerType.Substring(0, 1).ToUpper() + lowerType.Substring(1, lowerType.Length - 1);

                try
                {
                    searchType = (SearchType) Enum.Parse(typeof (SearchType), type);
                }
                catch
                {
                    // dont do anything for now.
                }
            }
            PhotoData photoData = new PhotoData();

            try
            {
                int pageValue = page == null ? 0 : page.Value - 1;

                if (searchType == SearchType.Tag)
                    photoData.Photos = model.GetPhotosForKey(q, true, pageValue, PHOTO_LIST_PAGE_LEN);
                else if (searchType == SearchType.User)
                    photoData.Photos = model.GetPhotosByUser(q, string.Empty, pageValue, PHOTO_LIST_PAGE_LEN);
                else
                    photoData.Photos = model.GetPhotosForKey(q, false, pageValue, PHOTO_LIST_PAGE_LEN);
                
                BuildPager(photoData);
            }
            catch (Exception ex)
            {
                this.ModelState.AddModelError("error", ex);
            }
            return photoData;
        }

        [MvcAction]
        public ActionResult Detail(string photoId)
        {
            PhotoDetail detail = null;
            try
            {
                detail = model.GetPhoto(photoId);
                detail.IsAuthenticated = model.IsAuthenticated();
            }
            catch (Exception ex)
            {
                this.ModelState.AddModelError("error", ex.Message);
            }

            return View(detail);
           
        }
        [CompressResponse, MvcAction, OutputCache(Location = OutputCacheLocation.Client, Duration = 216000, VaryByParam = "version" )]
        public ActionResult PopularTags(string version)
        {
            IEnumerable<PopularTag> list = model.GetPopularTags();
            return View(list);
        }

        [MvcAction]
        public ActionResult Tags(string name, int? page, string style)
        {
            ViewData["Tag"] = name;

            PhotoData photoData = new PhotoData();
            int pageValue = page == null ? 0 : page.Value - 1;
            photoData.Photos = model.GetPhotosByTag(name, pageValue, PHOTO_LIST_PAGE_LEN);
            BuildPager(photoData);

            return ViewPhoto(style, photoData);
        }

        private void BuildPager(PhotoData photoData)
        {
            ViewData["UserObject"] = secModel.GetAuthenticatedUser();

            if (photoData.Photos.Count > 0)
            {
                photoData.Total = photoData.Photos.Total;
                photoData.ShowPager = true;
            }
            else
            {
                this.ModelState.AddModelError("error", "Opps..no photos found. Try something else.");
                photoData.ShowPager = false;
            }
        }
    }
}
